/**
 * NextVisual
 */
/**
 * NextVisual
 */
package net.nextvisual.web.weixin;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;

import com.dcits.xsb.util.ServletUtils;
import com.dcits.xsb.util.StrUtils;
import com.jccatech.api.IMvcControl;

/**
 * 微信接入检查
 * 
 * @version 1.0
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since 销售宝 2.0
 * 
 *        <pre>
 * 历史：
 *      建立: 2014-3-8 lexloo
 * </pre>
 */
public class WeiXinControl implements IMvcControl {
    private static final String TOKEN = "loveyou741018";

    @At("/weixin/comm")
    @Ok("raw")
    public String report(@Param("signature") String signature,
                         @Param("timestamp") String timestamp,
                         @Param("nonce") String nonce,
                         @Param("echostr") String echostr,
                         HttpServletRequest request) {
        if (!this.checkSingature(signature, timestamp, nonce)) {
            return "";
        }

        if (!StrUtils.isEmpty(echostr)) {
            return echostr;
        } else {
            try {
                String docStr = ServletUtils.getInputDocString(request);
                Document doc = DocumentHelper.parseText(docStr);
                Element root = doc.getRootElement();
                String msgType = root.elementTextTrim("MsgType");
                String content;
                if ("text".equals(msgType)) {
                    content = "echo" + root.elementTextTrim("Content");
                } else {
                    content = "只支持文本类型";
                }

                StringBuilder sb = new StringBuilder("<xml>");
                sb.append("<ToUserName><![CDATA[")
                  .append(root.elementTextTrim("FromUserName"))
                  .append("]]></ToUserName>");
                sb.append("<FromUserName><![CDATA[")
                  .append(root.elementTextTrim("ToUserName"))
                  .append("]]></FromUserName>");
                sb.append("<CreateTime><![CDATA[").append(new Date().getTime()).append("]]></CreateTime>");
                sb.append("<MsgType><![CDATA[").append("text").append("]]></MsgType>");
                sb.append("<Content><![CDATA[").append(content).append("]]></Content>");
                sb.append("<FuncFlag><![CDATA[").append(0).append("</FuncFlag>");
                sb.append("</xml>");
                return sb.toString();
            } catch (DocumentException e) {
                e.printStackTrace();
            }

        }

        return "";
    }

    private boolean checkSingature(String signature, String timestamp, String nonce) {
        List<String> sList = new ArrayList<String>();
        sList.add(TOKEN);
        sList.add(nonce);
        sList.add(timestamp);

        Collections.sort(sList);

        String tmpStr = StrUtils.join(sList, "");
        return signature.equals(sha1(tmpStr));
    }

    private String sha1(String value) {
        MessageDigest messageDigest;
        try {
            messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(value.getBytes());

            return bytes2Hex(messageDigest.digest());

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        return null;
    }

    private String bytes2Hex(byte[] bts) {
        String des = "";
        String tmp = null;
        for (int i = 0; i < bts.length; i++) {
            tmp = (Integer.toHexString(bts[i] & 0xFF));
            if (tmp.length() == 1) {
                des += "0";
            }
            des += tmp;
        }
        return des;
    }
}
